#ifndef __CANYON_CORE
#define __CANYON_CORE

#include "arch.hpp"

#include "registers.hpp"
#include "memory.hpp"
#include "bus.hpp"

namespace canyon{

class VM{
    protected:
    bool   flag_skip = false;
    size_t step;

    protected:
    uint8_t memory_pool[MEMORY_SIZE] = {};

    public:
    Registers regs;
    Memory    memory;
    Bus       bus;

    public:
    VM(){
        this->memory = Memory(this->memory_pool, MEMORY_SIZE);
    }

    public:
    void     skip       (size_t);
    uint64_t get_codeadr();
    void     set_codeadr(size_t);

    public:
    // FUNCTIONS WITH *SEC* MEANS MAYBE UNSAFE
    void cmd_exit          (command);
    void cmd_mov_irx       (command, size_t);
    void cmd_mov_i0m       (command);
    void cmd_mov_r0r0      (command);
    void cmd_mov_rr        (command);
    void cmd_mov_rxm       (command, size_t);
    void cmd_mov_rm        (command);  /*SEC*/
    void cmd_mov_mrx       (command, size_t);
    void cmd_mov_mm        (command);
    void cmd_swap_rr       (command);
    void cmd_swap_mm       (command);
    void cmd_swap_r_0x     (command, size_t);
    void cmd_band          (command);
    void cmd_bor           (command);
    void cmd_bxor          (command);
    void cmd_bnot          (command);
    void cmd_bleft         (command);
    void cmd_bright        (command);
    void cmd_add           (command);
    void cmd_sub           (command);
    void cmd_mul           (command);
    void cmd_div           (command);
    void cmd_cmp           (command);
    void cmd_jmp           (command);
    void cmd_jmp_a_if_b    (command);
    void cmd_jmp_a_ifn_b   (command);
    void cmd_jmp_adr_ife   (command);
    void cmd_jmp_adr_ifne  (command);
    void cmd_jmp_adr_ifalb (command);
    void cmd_jmp_adr_ifagb (command);
    void cmd_jmp_adr_ifaleb(command);
    void cmd_jmp_adr_ifageb(command);
    void cmd_map_dm        (command);
    void cmd_umap_d        (command);
    void cmd_info_dev_count(command);
    void cmd_call_d        (command);

    public:
    void run_once(command);
    void run     (size_t entrypoint=0);
};
    
};

#endif
